***********************************
* Replication for "Patience Across Payday: The Role of Scarcity in Commitment Decisions"
* Data Analysis
* Author: Holly Dykstra 
* January 2025
************************************ 
************************************ 

set more off
clear all

***************************************************************
***************************************************************
***CHANGE TO CURRENT FOLDER

cd "~/..../"

***************************************************************
***************************************************************
***LOCAL DATASETS

local stata "stata.dta"

***************************************************************
*SECTION 3 RESULTS
***************************************************************

**** 3.1 When do participants feel cash-strapped?

* Figure 2: Low on Cash by Day Relative to Payday *

clear all
use `stata' if completed==1

ttest scarcity, by(before_payday)
prtest scarcity if treatment==1|treatment==5, by(treatment)
prtest scarcity if treatment==2|treatment==5, by(treatment)
prtest scarcity if treatment==3|treatment==5, by(treatment)
prtest scarcity if treatment==4|treatment==5, by(treatment)

collapse (mean) meanscarcity=scarcity (sebinomial) sescarcity=scarcity (count) n=scarcity, by(treatment)

gen hiscarcity = meanscarcity + sescarcity
gen lowscarcity = meanscarcity - sescarcity

twoway (bar meanscarcity treatment, fcolor(gs0) lcolor(gs13) barw(0.6)) (rcap hiscarcity lowscarcity treatment, lcolor(gray) msize(vsmall)), ytitle(Proportion Low on Cash) ylabel(0.5(.1).8, format(%03.2f)) ymtick(0.5(0.05)0.8, ticks grid) xtitle("Timing of Decision" "{it:d} = Payday") xscale(noline) xline(4.5, noextend) xlabel(1 "{it:d} - 11" 2 "{it:d} - 8" 3 "{it:d} - 5" 4 "{it:d} - 2" 5 "{it:d} + 1", noticks nogrid) legend(off)

graph export results_scarcity_SE.eps, replace fontface(Times)

**** 3.2 Does the timimg of the decision matter?

* Table 1: Commitment by Day Relative to Payday *

clear all
use `stata' if completed==1

eststo x1: quietly regress choice b5.treatment i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust
eststo x2: quietly regress choice b5.treatment financialwellbeing i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust
eststo x3: quietly regress choice b5.treatment financialwellbeing i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month i.gender b5.age_group b2.education_group i.race i.marriage i.income_group, robust

eststo x4: quietly regress choice b5.treatment i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month if allincome_dum==0, robust
eststo x5: quietly regress choice b5.treatment financialwellbeing i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month if allincome_dum==0, robust
eststo x6: quietly regress choice b5.treatment financialwellbeing i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month i.gender b5.age_group b2.education_group i.race i.marriage i.income_group if allincome_dum==0, robust

esttab x1 x2 x3 x4 x5 x6 using results_nostars.tex, drop(*.recordeddate*) replace label mgroups("Full Sample" "One Source of Income", pattern(1 0 0 1 0 0) prefix(\multicolumn{@span}{c}{) suffix(}) span erepeat(\cmidrule(lr){@span})) se(3) b(3) nobaselevels mlabels(none) eqlabels(none) nolegend nostar stats(N, fmt(0 2) labels(`"Observations"' )) indicate("Demographic Controls = *gender* *age_group* *education_group* *income_group* *race* *marriage*", labels("X" ""))

*F-test
reg choice b5.treatment
test 1.treatment=2.treatment=3.treatment=4.treatment=5.treatment

***************************************************************
*SECTION 4: Discussion
***************************************************************

**** 4.2 Is there heterogeneity in willingness to commit?

* Figure 3: Commitment by Demographic Characteristic *

*By gender

clear all
use `stata' if completed==1
collapse (mean) meanchoice=choice (sebinomial) sechoice=choice, by(gender treatment)

gen hichoice = meanchoice + sechoice
gen lowchoice = meanchoice - sechoice

twoway (line meanchoice treatment if gender == 0, lcolor(black) lpattern(solid) legend(label(1 "Male"))) (line meanchoice treatment if gender == 1, lcolor(black) lpattern(dash) legend(label(2 "Female"))) (rcap hichoice lowchoice treatment if gender == 0, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if gender == 1, lcolor(gs12) msize(vsmall)), ytitle(Proportion Choosing to Commit) ylabel(.1(.1).6, format(%03.2f)) ymtick(.1(.05).6,grid) xscale(noline) xline(4.5, noextend) xlabel(1 "{it:d} - 11" 2 "{it:d} - 8" 3 "{it:d} - 5" 4 "{it:d} - 2" 5 "{it:d} + 1", noticks nogrid) legend(subtitle("Gender Group", size(*.8)) position(5) span rows(2) size(*.7) region(lcolor(black)) order(1 2)) aspect(0.85) ysize(5.5)

graph export results_gender.eps, replace fontface(Times)

*By Age Group
clear all
use `stata' if completed==1

collapse (mean) meanchoice=choice (sebinomial) sechoice=choice, by(age_combined treatment)

gen hichoice = meanchoice + sechoice
gen lowchoice = meanchoice - sechoice

twoway (line meanchoice treatment if age_combined == 0, lcolor(black) lpattern(solid) legend(label(1 "Under 35"))) (line meanchoice treatment if age_combined == 1, lcolor(black) lpattern(dash) legend(label(2 "35+"))) (rcap hichoice lowchoice treatment if age_combined == 0, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if age_combined == 1, lcolor(gs12) msize(vsmall)), ytitle(Proportion Choosing to Commit) ylabel(.1(.1).6, format(%03.2f)) ymtick(.1(.05).6,grid) xscale(noline) xline(4.5, noextend) xlabel(1 "{it:d} - 11" 2 "{it:d} - 8" 3 "{it:d} - 5" 4 "{it:d} - 2" 5 "{it:d} + 1", noticks nogrid) legend(subtitle("Age Group", size(*.8)) position(5) span rows(2) size(*.7) region(lcolor(black)) order(1 2)) aspect(0.85) ysize(5.5)

graph export results_age.eps, replace fontface(Times)

*By Education
clear all
use `stata' if completed==1

drop if education_group == 0
collapse (mean) meanchoice=choice (sebinomial) sechoice=choice, by(education_group treatment)

gen hichoice = meanchoice + sechoice
gen lowchoice = meanchoice - sechoice

twoway (line meanchoice treatment if education_group == 1, lcolor(black) lpattern(solid) legend(label(1 "High School or Equivalent"))) (line meanchoice treatment if education_group == 2, lcolor(black) lpattern(dot) legend(label(2 "Some College or Associate's Degree"))) (line meanchoice treatment if education_group == 3, lcolor(black) lpattern(dash_dot) legend(label(3 "Bachelor's Degree"))) (line meanchoice treatment if education_group == 4, lcolor(black) lpattern(longdash) legend(label(4 "Graduate Degree"))) (rcap hichoice lowchoice treatment if education_group == 1, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if education_group == 2, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if education_group == 3, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if education_group == 4, lcolor(gs12) msize(vsmall)), ytitle(Proportion Choosing to Commit) ylabel(0(.1).7, format(%03.2f)) ymtick(0(.05).7,grid) xscale(noline) xline(4.5, noextend) xlabel(1 "{it:d} - 11" 2 "{it:d} - 8" 3 "{it:d} - 5" 4 "{it:d} - 2" 5 "{it:d} + 1", noticks nogrid) legend(subtitle("Education Group", size(*.8)) position(5) span rows(2) size(*.7) region(lcolor(black)) order(1 2 3 4)) aspect(0.85) ysize(5.5)

graph export results_education.eps, replace fontface(Times)

*By Income
clear all
use `stata' if completed==1

collapse (mean) meanchoice=choice (sebinomial) sechoice=choice (count) n=choice, by(income_combined treatment)

gen hichoice = meanchoice + sechoice
gen lowchoice = meanchoice - sechoice

twoway (line meanchoice treatment if income_combined == 0, lcolor(black) lpattern(solid) legend(label(1 "Less than $50,000"))) (line meanchoice treatment if income_combined == 1, lcolor(black) lpattern(dot) legend(label(2 "$50,000 - $99,999"))) (line meanchoice treatment if income_combined == 2, lcolor(black) lpattern(dash) legend(label(3 "Over $100,000"))) (rcap hichoice lowchoice treatment if income_combined == 0, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if income_combined == 1, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if income_combined == 2, lcolor(gs12) msize(vsmall)), ytitle(Proportion Choosing to Commit) ylabel(.1(.1).6, format(%03.2f)) ymtick(.1(.05).6,grid) xscale(noline) xline(4.5, noextend) xlabel(1 "{it:d} - 11" 2 "{it:d} - 8" 3 "{it:d} - 5" 4 "{it:d} - 2" 5 "{it:d} + 1", noticks nogrid) legend(subtitle("Income Group", size(*.8)) position(5) span rows(2) size(*.7) region(lcolor(black)) order(1 2 3)) aspect(0.85) ysize(5.5)

graph export results_income.eps, replace fontface(Times)


*By ability to raise $2,000
clear all
use `stata' if completed==1

collapse (mean) meanchoice=choice (sebinomial) sechoice=choice, by(emergency_canraise treatment)

gen hichoice = meanchoice + sechoice
gen lowchoice = meanchoice - sechoice

twoway (line meanchoice treatment if emergency_canraise == 0, lcolor(black) lpattern(solid) legend(label(1 "Cannot Raise $2,000"))) (line meanchoice treatment if emergency_canraise == 1, lcolor(black) lpattern(dash) legend(label(2 "Can Raise $2,000"))) (rcap hichoice lowchoice treatment if emergency_canraise == 0, lcolor(gs12) msize(vsmall)) (rcap hichoice lowchoice treatment if emergency_canraise == 1, lcolor(gs12) msize(vsmall)), ytitle("Proportion Choosing to Commit") ylabel(.1(.1).6, format(%03.2f)) ymtick(.1(.05).6, grid) xscale(noline) xline(4.5, noextend) xlabel(1 "{it:d} - 11" 2 "{it:d} - 8" 3 "{it:d} - 5" 4 "{it:d} - 2" 5 "{it:d} + 1", noticks nogrid) legend(subtitle("Ability to Raise $2,000", size(*.8)) position(5) span rows(2) size(*.7) region(lcolor(black)) order(1 2)) aspect(0.85) ysize(5.5)

graph export results_emergency.eps, replace fontface(Times)

*Other analyses
clear all
use `stata' if completed==1

prtest choice if (treatment==2|treatment==5)&education_hs==1, by(treatment)

**** 4.3 Was there differential attrition across treatment groups?

clear all
use `stata'

* Table 2: Descriptive Statistics of Attrition by Treatment Day *
tab treatment completed, chi2

* Table 3: OLS Regression of Attrition by Treatment Day *
eststo x1: quietly reg completed b5.treatment, robust
eststo x2: quietly reg completed b5.treatment i.chosendate_week i.chosendate_month i.chosendate_dayofweek, robust
eststo x3: quietly reg completed b5.treatment if allincome_dum==0, robust
eststo x4: quietly reg completed b5.treatment i.chosendate_week i.chosendate_month i.chosendate_dayofweek if allincome_dum==0, robust

esttab x1 x2 x3 x4 using attrition.tex, replace label mgroups("Full Sample" "One Source of Income", pattern(1 0 1 0) prefix(\multicolumn{@span}{c}{) suffix(}) span erepeat(\cmidrule(lr){@span})) se(3) b(3) nobaselevels mlabels(none) eqlabels(none) nolegend nostar stats(N, fmt(0 2) labels(`"Observations"' )) indicate("Return date controls = *chosendate*", labels("X" ""))


***************************************************************
* APPENDIX
***************************************************************

**** 7.2 Additional Tables
**** 7.2.1 Descriptive Statistics

clear all
use `stata' if completed==1

table gender, statistic(percent)
table age_group, statistic(percent)
table race, statistic(percent)
table education, statistic(percent)
table marriage, statistic(percent)
table income_group, statistic(percent)
table employment, statistic(percent)
table emergency_money, statistic(percent)
sum credit_number, d
sum credit_amount, d

**** 7.2.2 Balance

* Table 5: Balance Table by Treatment Day *

clear all
use `stata' if completed==1

local balvars gender age white bachelors married inc25_49 fulltime  

iebaltab `balvars', grpvar(treatment) feqtest onerow stats(desc(se) pair(none)) rowlabels("gender Female @ age Age @ white Caucasian @ bachelors Bachelor's degree @ married Married @ inc25_49 Income \textdollar25,000-\textdollar49,000 @ fulltime Works full-time") tblnonote savetex(balancetable.tex) replace 


**** 7.2.3 Robustness Checks

* Table 6: Commitment by Day Relative to Payday without Time Controls *
clear all
use `stata' if completed==1

eststo x1: quietly regress choice b5.treatment, robust
eststo x2: quietly regress choice b5.treatment financialwellbeing, robust
eststo x3: quietly regress choice b5.treatment financialwellbeing i.gender b5.age_group b2.education_group i.race i.marriage i.income_group, robust

eststo x4: quietly regress choice b5.treatment if allincome_dum==0, robust
eststo x5: quietly regress choice b5.treatment financialwellbeing  if allincome_dum==0, robust
eststo x6: quietly regress choice b5.treatment financialwellbeing i.gender b5.age_group b2.education_group i.race i.marriage i.income_group if allincome_dum==0, robust

esttab x1 x2 x3 x4 x5 x6 using results_nostars_notime.tex, replace label mgroups("Full Sample" "One Source of Income", pattern(1 0 0 1 0 0) prefix(\multicolumn{@span}{c}{) suffix(}) span erepeat(\cmidrule(lr){@span})) se(3) b(3) nobaselevels mlabels(none) eqlabels(none) nolegend nostar stats(N, fmt(0 2) labels(`"Observations"' )) indicate("Demographic Controls = *gender* *age_group* *education_group* *income_group* *race* *marriage*", labels("X" ""))



* Table 7: Proportion Choosing to Commit by Day *

clear all
use `stata' if completed==1

prtest choice if treatment==5|treatment==4, by(treatment)
prtest choice if treatment==5|treatment==3, by(treatment)
prtest choice if treatment==5|treatment==2, by(treatment)
prtest choice if treatment==5|treatment==1, by(treatment)

* Table 8: Randomization Inference Results: Proportion Choosing to Commit by Day *

clear all
use `stata' if completed==1

* Randomization inference					

randcmd ((treat1 treat2 treat3 treat4) reg choice treat1 treat2 treat3 treat4, robust), treatvars(treat1 treat2 treat3 treat4) reps(10000)

randcmd ((treat1 treat2 treat3 treat4) reg choice treat1 treat2 treat3 treat4 i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust), treatvars(treat1 treat2 treat3 treat4) reps(10000)


**** 7.2.4 Classification of Free-Text Responses

clear all
use `stata' if completed==1

*Create a list of gpt vars 
unab gptvars: *_gpt

*Break these into whether took up commitment
local ncommit_vars ""
local commit_vars ""

foreach var of varlist `gptvars' {
    if regexm("`var'", "^l_") {
        local commit_vars "`commit_vars' `var'"
    }
    else {
        local ncommit_vars "`ncommit_vars' `var'"
    }
}

* Table 9: Classification of Responses: Did Not Choose Commitment*

foreach var of varlist `ncommit_vars' {
    tabulate `var' if choice == 0
}

* Table 10: Classification of Responses: Chose Commitment *

foreach var of varlist `commit_vars' {
    tabulate `var' if choice == 1
}


**** 7.2.5. Additional Analyses

* Table 11: Heterogeneity of Commitment by Day Relative to Payday *

clear all
use `stata' if completed==1

eststo x1: quietly regress choice b5.treatment i.gender i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust
eststo x2: quietly regress choice b5.treatment i.age_combined i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust
eststo x3: quietly regress choice b5.treatment b3.education_group i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust
eststo x4:quietly regress choice b5.treatment b1.income_combined i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust
eststo x5:quietly regress choice b5.treatment b0.emergency_cannotraise i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust
eststo x6:quietly regress choice b5.treatment financialwellbeing i.recordeddate_dayofweek i.recordeddate_week i.recordeddate_month, robust

esttab x1 x2 x3 x4 x5 x6 using results_het.tex, drop(*.recordeddate*) replace label style(tex) se(3) b(3) nobaselevels mlabels(none) eqlabels(none) nolegend nostar stats(N, fmt(0 2) labels("Observations")) refcat(0.education_group "\textit{Education}" 0.income_combined "\textit{Income}", nolabel)

